home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / a86v307b.arc / 09DIRC.DOC < prev   
Text File  |  1987-07-13  |  26KB  |  592 lines

  1. CHAPTER 9   DIRECTIVES IN A86                             9-1
  2.  
  3.  
  4. Segments in A86
  5.  
  6. The following discussion applies when A86 is assembling a .COM 
  7. program.  See the next chapter for the discussion of segmentation 
  8. for .OBJ files.
  9.  
  10. A86 views the 86 computer's memory space as having two parts: The 
  11. first part is the program, whose contents are the object bytes 
  12. generated by A86 during its assembly of the source.   A86 calls 
  13. this area the CODE SEGMENT.  The second part is the data area, 
  14. whose contents are generated by the program after it starts 
  15. running.  A86 calls this area the DATA SEGMENT.  
  16.  
  17. Please note well that the only difference between the CODE and 
  18. DATA segments is whether the contents are generated by the 
  19. program or the assembler.  The names CODE and DATA suggest that 
  20. program code is placed in the CODE segment, and data structures 
  21. go in the DATA segment.  This is mostly true, but there are 
  22. exceptions.  For example, there are many data structures whose 
  23. contents are determined by the assembler: pointer tables, arrays 
  24. of pre-defined constants, etc.  These tables are assembled in the 
  25. CODE segment.  
  26.  
  27. In general, you will want to begin your program with the 
  28. directive DATA SEGMENT, followed by an ORG statement giving the 
  29. address of the start of your data area.  You then list all your 
  30. program variables and uninitialized data structures, using the 
  31. directives DB, DW, and STRUC.  A86 will allocate space starting 
  32. at the address given in the ORG statement, but it will not 
  33. generate any object bytes in that space.  After your data segment 
  34. declarations, you provide a CODE SEGMENT directive, following by 
  35. an ORG giving the address of the start of your program.  You 
  36. follow this with the program itself, together with any assembler-
  37. generated data structures.  A short program illustrating this 
  38. suggested usage follows: 
  39.  
  40. DATA SEGMENT
  41. ORG 08000
  42.   ANSWER_BYTE  DB ?
  43.   CALL_COUNT   DW ?
  44.  
  45. CODE SEGMENT
  46.   JMP MAIN
  47.  
  48. TRAN_TABLE:
  49.   DB 16,3,56,23,0,9,12,7
  50.  
  51. MAIN:
  52.   MOV BX,TRAN_TABLE
  53.   XLATB
  54.   MOV ANSWER_BYTE,AL
  55.   INC CALL_COUNT
  56.   RET
  57.                                                           9-2
  58. A86 allows you to intersperse CODE SEGMENTs and DATA SEGMENTs 
  59. throughout your program; but in general it is best to put all 
  60. your DATA SEGMENT declarations at the top of your program, to 
  61. avoid problems with forward-referencing.  
  62.  
  63.  
  64. CODE ENDS and DATA ENDS Statements
  65.  
  66. For compatibility with Intel/IBM assemblers, A86 provides the 
  67. CODE ENDS and DATA ENDS statements.  The CODE ENDS statement is 
  68. ignored; we assume that you have not nested a CODE segment inside 
  69. a DATA segment.  The DATA ENDS statement is equivalent to a CODE 
  70. SEGMENT statement.  
  71.  
  72.  
  73.  
  74. The ORG Directive
  75.  
  76. Syntax: ORG address
  77.  
  78. ORG moves the output pointer for the segment currently being 
  79. assembled to the value of the operand, which should be an 
  80. absolute constant, or an expression evaluating to an absolute, 
  81. non-forward-referenced constant.  
  82.  
  83. ORG is most often used in a DATA segment, to control the location 
  84. of the data area within the segment.  For example, in programs 
  85. that fit entirely into 64K, you provide an ORG directive as the 
  86. first line within your DATA segment at the top of your program.  
  87. The location given by the ORG is some location that you are sure 
  88. will be beyond the end of your program.  If you are sure that 
  89. your program will not go beyond 8K (02000 hex), your program can 
  90. look like this: 
  91.  
  92. DATA SEGMENT
  93. ORG 02000       ; data goes here, beyond the end of the program
  94.  
  95. (your data segment variable and buffer declarations go here)
  96.  
  97. DATA ENDS
  98.  
  99. (your program goes here)
  100.  
  101.  
  102. There is a special side-effect to ORG when it is used in the CODE 
  103. segment.  If you begin your code segment with ORG 0, then A86 
  104. knows that you are not assembling a .COM program; but are instead 
  105. assembling a code segment to be used in some other context 
  106. (examples: programming a ROM, or assembling a procedure for Turbo 
  107. Pascal).  The output file will start at 0, not 0100 as in a .COM 
  108. file; and the default extension for the output file will be .BIN, 
  109. not .COM.  
  110.                                                           9-3
  111. Other than in the above example, you should not in general issue 
  112. an ORG within the CODE segment that would lower the value of the 
  113. output pointer.  This is because you thereby put yourself in 
  114. danger of losing part of your assembled program.  If you re-
  115. assemble over space you have already assembled, you will clobber 
  116. the previously-assembled code.  Also, be aware that the size of 
  117. the output program file is determined by the value of the code 
  118. segment output pointer when the program stops.  If you ORG to a 
  119. lower value at the end of your program, the output program file 
  120. will be truncated to the lower-value address.  
  121.  
  122. Again, almost no program producing a .COM file will need any ORG 
  123. directive in the code segment.  There is an implied ORG 0100 at 
  124. the start of the program.  You just start coding instructions, and 
  125. the assembler will put them in the right place.  
  126.  
  127.  
  128. The EVEN Directive
  129.  
  130. Syntax: EVEN
  131.  
  132. The EVEN directive coerces the current output pointer to an even 
  133. value.  It does so by adding 1 to the pointer is the pointer was 
  134. odd; doing nothing if the pointer was already even.  EVEN is most 
  135. often used in data segments, before a sequence of DW directives.  
  136. The 16-bit machines of the 86 family fetch words more quickly 
  137. when they are aligned onto even addresses; so the EVEN directive 
  138. insures that your program will have the faster access to those 
  139. DW's that follow it.  (This speed improvement will not be seen on 
  140. the 8-bit machines, most notably the 8088 of the original IBM-
  141. PC.) 
  142.  
  143.  
  144. Data Allocation Using DB, DW, DD, DQ, and DT
  145.  
  146. The 86 computer family supports the three fundamental data types 
  147. BYTE, WORD, and DOUBLEWORD. A byte is eight bits, a word is 16 
  148. bits (2 bytes), and a doubleword is 32 bits (4 bytes).   In 
  149. addition, the 87 floating-point processor manipulates 8-byte 
  150. quantities, which we call Q-words, and 10-byte quantities, which 
  151. we call T-words. The A86 data allocation statement is used to 
  152. specify the bytes, words, doublewords, Q-words, and T-words which 
  153. your program will use as data. The syntax for the data allocation 
  154. statement is as follows: 
  155.  
  156. (optional var-name)  DB  (list of values)
  157. (optional var-name)  DW  (list of values)
  158. (optional var-name)  DD  (list of values)
  159. (optional var-name)  DQ  (list of values)
  160. (optional var-name)  DT  (list of values)
  161.                                                           9-4
  162. The variable name, if present, causes that name to be entered 
  163. into the symbol table as a memory variable with type BYTE (for 
  164. DB), WORD (for DW), DWORD (for DD), QWORD (for DQ), or TBYTE (for 
  165. DT). The variable name should NOT have a colon after it, unless 
  166. you wish the name to be a label (instructions referring to it 
  167. will interpret the label as the constant pointer to the memory 
  168. location, not its contents).  
  169.  
  170. The DB statement is used to reserve bytes of storage; DW is used 
  171. to reserve words.  The list of values to the right of the DB or 
  172. DW serves two purposes.  It specifies how many bytes or words are 
  173. allocated by the statement, as well as what their initial values 
  174. should be.  The list of values may contain a single value or more 
  175. than one, separated by commas.  The list can even be missing; 
  176. meaning that we wish to define a byte or word variable at the 
  177. same location as the next variable.  
  178.  
  179. If the data initialization is in the DATA segment, the values 
  180. given are ignored, except as place-markers to reserve the 
  181. appropriate number of units of storage.  The use of "?", which 
  182. in .COM mode is a synonym for zero, is recommended in this 
  183. context to emphasize the lack of actual memory initialization.  
  184. When A86 is assembling .OBJ files, the ?-initialization will 
  185. cause a break in the segment (unless ? is embedded in a nested 
  186. DUP containing non-? terms, in which case it is a synonym for 
  187. zero).
  188.                  
  189. A special value which can be used in data initializations is the 
  190. DUP construct, which allows the allocation and/or initialization 
  191. of blocks of data.  The expression  n DUP x  is equivalent to a 
  192. list with x repeated n times.  "x" can be either a single value, 
  193. a list of values, or another DUP construct nested inside the 
  194. first one.  The nested DUP construct needs to be surrounded by 
  195. parentheses.  All other assemblers, and earlier versions of A86, 
  196. require parentheses around all right-operands to DUP, even simple 
  197. ones; but this requirement has been removed for simple operands 
  198. in the current A86.
  199.  
  200. Here are some examples of data initialization statements, with 
  201. and without DUP constructs: 
  202.  
  203. CODE SEGMENT
  204.   DW 5                    ; allocate one word, init. to 5
  205.   DB 0,3,0                ; allocate three bytes, init. to 0,3,0
  206.   DB 5 DUP 0              ; equivalent to DB 0,0,0,0,0
  207.   DW 2 DUP (0,4 DUP 7)    ; equivalent to DW 0,7,7,7,7,0,7,7,7,7
  208.  
  209. DATA SEGMENT
  210. XX      DW ?      ; define a word variable XX
  211. YYLOW   DB        ; no init value: YYLOW is low byte of word var YY
  212. YY      DW ?
  213. X_ARRAY DB  100 DUP ?     ; X_ARRAY is a 100-byte array
  214. D_REAL  DQ ?              ; double-precision floating variable
  215. EX_REAL DT ?              ; extended precision floating variable
  216.                                                           9-5
  217. A character string value may be used to initialize consecutive 
  218. bytes in a DB statement.  Each character will be represented by 
  219. its ASCII code.  The characters are stored in the order that they 
  220. appear in the string, with the first character assigned to the 
  221. lowest-addressed byte.  In the DB statement that follows, five 
  222. bytes are initialized with the ASCII representation of the 
  223. characters in the string 'HELLO': 
  224.  
  225. DB 'HELLO'
  226.  
  227. Note that the DB directive is the only place in your program that 
  228. strings of length greater than 2 may occur.  In all other 
  229. contexts (including DW), a string is treated as the constant 
  230. number represent the ASCII value of the string; for example, CMP 
  231. AL,'#' is the instruction comparing the AL-register with the 
  232. ASCII value of the pound-sign.  Note further that 2-character 
  233. string constants, like all constants in the 8086, have their 
  234. bytes reversed.  Thus, while DB 'AB' will produce hex 41 followed 
  235. by hex 42, the similar-looking DW 'AB' reverses the bytes: hex 42 
  236. followed by hex 41.  
  237.  
  238. For compatibility, A86 now accepts double-quotes, as well as 
  239. single-quotes, for strings in DB directives.
  240.  
  241.  
  242. The DD directive is used to initialize 32-bit doubleword pointers 
  243. to locations in arbitrary segments of the 86's memory space.  
  244. Values for such pointers are given by two numbers separated by a 
  245. colon.  The segment register value appears to the left of the 
  246. colon; and the offset appears to the right of the colon.  In 
  247. keeping with the reversed-bytes nature of memory storage in the 
  248. 86 family, the offset comes first in memory.  For example, the 
  249. statement 
  250.  
  251.    DD 01234:05678
  252.  
  253. appearing in a CODE segment will cause the hex bytes 78 56 34 12 
  254. to be generated, which is a long pointer to segment 01234, offset 
  255. 05678.  
  256.  
  257. DD, DQ, and DT can also be used to initialize large integers and 
  258. floating-point numbers.  Examples:
  259.  
  260.   DD 500000   ; half-million, too big for most 86 instructions
  261.   DD 3.5      ; single-precision floating-point number
  262.   DQ 3.5      ; the same number in a double-precision format
  263.   DT 3.5      ; the same number in an extended-precision format
  264.                                                           9-6
  265. The STRUC Directive
  266.  
  267. The STRUC directive is used to define a template of data to be 
  268. addressed by one of the 8086's base and/or index registers.  The 
  269. syntax of STRUC is as follows: 
  270.  
  271. (optional strucname)  STRUC  (optional effective address)
  272.  
  273. The optional structure name given at the beginning of the line 
  274. can appear in subsequent expressions in the program, with the 
  275. operator TYPE applied to it, to yield the number of bytes in the 
  276. structure template.  
  277.  
  278. The STRUC directive causes the assembler to enter a mode similar 
  279. to DATA SEGMENT, with the optional addition of indexing: if an 
  280. effective address, which can include base registers [BX] or [BP] 
  281. and/or index registers [SI] or [DI], is given at the end of the 
  282. STRUC line, all variables declared between STRUC and ENDS will be 
  283. indexed by the effective address.  For example: 
  284.  
  285. LINE STRUC [BP]
  286.        DB 80 DUP (?)
  287. LSIZE  DB ?
  288. LPROT  DB ?
  289.      ENDS
  290.  
  291. The above STRUC defines the variables LSIZE, equivalent to 
  292. [BP+80], and LPROT, equivalent to [BP+81].  You can now issue 
  293. instructions such as MOV AL,LSIZE; which automatically generates 
  294. the correct indexing for you.  
  295.  
  296. The mode entered by STRUC is terminated by the ENDS directive, 
  297. which returns the assembler to whatever segment (CODE or DATA) it 
  298. was in before the STRUC.  
  299.  
  300.  
  301.  
  302. Forward References
  303.  
  304. A86 allows names for a variety of program elements to be forward 
  305. referenced.  This means that you may use a symbol in one 
  306. statement and define it later with another statement.  For 
  307. example: 
  308.  
  309.   JNZ TARGET
  310.    .
  311.    .
  312. TARGET:
  313.   ADD AX,10
  314.  
  315. In this example, a conditional jump is made to TARGET, a label 
  316. farther down in the code.  When JNZ TARGET is seen, TARGET is 
  317. undefined, so this is a forward reference.  
  318.                                                           9-7
  319. Earlier versions of A86 were much more restricted in the kinds of 
  320. forward references allowed.  Most of the restrictions have now 
  321. been eased, for convenience as well as compatibility with other 
  322. assemblers.  In particular, you may now make forward references 
  323. to variable names.  You just need to see to it that A86 has 
  324. enough information about the type of the operand to generate the 
  325. correct instruction.  For example, MOV FOO,AL will cause A86 to 
  326. correctly deduce that FOO is a byte variable.  You can even code 
  327. a subsequent MOV FOO,1 and A86 will remember that FOO was assumed 
  328. to be a byte variable.  But if you code MOV FOO,1 first, A86 
  329. won't know whether to issue a byte or a word MOV instruction; and 
  330. will thus issue an error message.  You then specify the type by
  331. MOV FOO B,1.
  332.  
  333. In general, A86's compatibility with That Other assembler has 
  334. improved dramatically for forward references.  Now, for most 
  335. programs, you need only sprinkle a very few B's and W's into your 
  336. references.  And you'll be rewarded: in many cases the word-form 
  337. is longer than the byte form, so that the other assembler winds 
  338. up inserting a wasted NOP in your program.  You'll wind up with 
  339. tighter code by using A86!
  340.  
  341.  
  342. Forward References in Expressions
  343.  
  344. A86 now allows you to add or subtract a constant number from a 
  345. forward-reference symbol; and to append indexing registers to a 
  346. forward-reference symbol.  This covers a vast majority of 
  347. expressions formerly disallowed.  For the remaining, more 
  348. complicated expressions, there is a trick you can use to work 
  349. your way around almost any case where you might run into a
  350. forward-reference restriction.  The trick is to move the 
  351. expression evaluation down in your program so that it no longer 
  352. contains a forward reference; and forward-reference the 
  353. evaluation answer.  For example, suppose you wish to advance the 
  354. ES segment register to point immediately beyond your program.  
  355. If PROG_SIZE is the number of bytes in your program, then you
  356. add (PROGSIZE+15)/16 to the program's segment register value.  
  357. This value is known at assembly-time; but it isn't known until 
  358. the end of the program.  You do the following:
  359.  
  360.      MOV AX,CS        ; fetch the program's segment value
  361.      ADD AX,SEG_SIZE  ; use a simple forward reference
  362.      MOV ES,AX        ; ES is now loaded as desired
  363.  
  364. Then at the end of the program you evaluate the expression:
  365.  
  366.      PROG_SIZE EQU $
  367.      SEG_SIZE EQU (PROG_SIZE+15)/16
  368.  
  369.                                                           9-8
  370. The EQU Directive
  371.  
  372. Syntax: symbol-name EQU expression
  373.         symbol-name EQU built-in-symbol
  374.         symbol-name EQU INT n
  375.  
  376. The expression field may specify an operand of any type that 
  377. could appear as an operand to an instruction.  
  378.  
  379. As a simple example, suppose you are writing a program that 
  380. manipulates a table containing 100 names and that you want to 
  381. refer to the maximum number of names throughout the source file.  
  382. You can, of course, use the number 100 to refer to this maximum 
  383. each time, as in MOV CX,100, but this approach suffers from two 
  384. weaknesses.  First of all, 100 can mean a lot of things; in the 
  385. absence of comments, it is not obvious that a particular use of 
  386. 100 refers to the maximum number of names.  Secondly, if you 
  387. extend the table to allow 200 names, you will have to locate each 
  388. 100 and change it to a 200.  Suppose, instead, that you define a 
  389. symbol to represent the maximum number of names with the 
  390. following statement: 
  391.  
  392. MAX_NAMES EQU 100
  393.  
  394. Now when you use the symbol MAX_NAMES instead of the number 100 
  395. (for example, MOV CX,MAX_NAMES), it will be obvious that you are 
  396. referring to the maximum number of names in the table.  Also, if 
  397. you decide to extend the table, you need only change the 100 in 
  398. the EQU directive to a 200 and every reference to MAX_NAMES will 
  399. reflect the change.  
  400.  
  401. You could also take advantage of A86's strong-typing, by changing 
  402. MAX_NAMES to a variable: 
  403.  
  404. MAX_NAMES  DB ?
  405.  
  406. or even an indexed quantity:
  407.  
  408. MAX_NAMES EQU [BX+1]
  409.  
  410. Because the A86 language is strongly-typed, the instruction for 
  411. loading MAX_NAMES into the CX-register remains exactly the same 
  412. in all cases: simply MOV CX,MAX_NAMES.  
  413.                                                           9-9
  414.  
  415. Equates to Built-In Symbols
  416.  
  417. A86 allows you to define synonyms for any of the assembler 
  418. reserved-symbols, by EQUating an alternate name of your choosing, 
  419. to that symbol.  For example, suppose you were coding a source 
  420. module that is to be incorporated into several different 
  421. programs.  In some programs, a certain variable will exist in the 
  422. code segment.  In others, it will exist in the stack segment.  
  423. You want to address the variable in the common source module, but 
  424. you don't know which segment-override to use.  The solution is to 
  425. declare a synonym, QS, for the segment register.  QS will be 
  426. defined by each program: the code-segment program will have a QS 
  427. EQU CS at the top of it; the stack-segment program will have QS 
  428. EQU SS.  The source module can use QS as an override, just as if 
  429. it were CS or SS.  The code would be, for example, QS MOV 
  430. AL,VARNAME.  
  431.  
  432. The NIL Prefix
  433.  
  434. A86 provides a mnemonic, NIL, that generates no code.  NIL can be 
  435. used as a prefix to another instruction (which will have no 
  436. effect on that instruction), or it can appear by itself on a 
  437. line.  NIL is provided to extend the example in the previous 
  438. section, to cover the possibility of no-overrides.  If your 
  439. source module goes into a program that fits into 64K, so that all 
  440. the segment registers have the same value, then code QS EQU NIL 
  441. at the top of that program.  
  442.  
  443.  
  444. Interrupt Equates
  445.  
  446. A86 allows you to equate your own name to an INT-instruction with 
  447. a specific interrupt-number.  For example, if you place  TRAP EQU 
  448. INT 3  at the top of your program, you can use the name TRAP as a 
  449. synonym for INT 3  (the debugger trap on the 8086).  
  450.  
  451.                                                           9-10
  452. Duplicate Definitions
  453.  
  454. A86 contains the unique feature of duplicate definitions.   We 
  455. have already discussed local symbols, which can be redefined to 
  456. different values without restriction.  Local symbols are the only 
  457. symbols that can be redefined.  However, any symbol can be 
  458. defined more than once, as long as the symbol is defined to be 
  459. the same value and type in each definition.  
  460.  
  461. This feature has two uses.  First, it eases modular program 
  462. development.  For example, if two independently-developed source 
  463. files both use the symbol ESC to stand for the ASCII code for 
  464. ESCAPE, they can both contain the declaration ESC EQU 01B, with 
  465. no problems if they are combined into the same program.  
  466.  
  467. The second use for this feature is assertion-checking.  Your 
  468. deliberate redeclaration of a symbol name is an assertion that 
  469. the value of the symbol has not changed; and you want the 
  470. assembler to issue you an error message if it has changed.  
  471. Example: suppose you have declared a table of options in your 
  472. DATA segment; and you have another table of initial values for 
  473. those options in your CODE segment.  If you come back months 
  474. later and add an option to your tables, you want to be reminded 
  475. to update both tables in the same way.  You should declare your 
  476. tables as follows: 
  477.  
  478. DATA SEGMENT
  479.   OPTIONS:
  480.     .
  481.     .
  482.   OPT_COUNT EQU $-OPTIONS    ; OPT_COUNT is the size of the table
  483.  
  484. CODE SEGMENT
  485.   OPT_INITS:
  486.     .
  487.     .
  488.   OPT_COUNT EQU $-OPT_INITS  ; second OPT_COUNT had better be the same!
  489.  
  490.  
  491.  
  492. The = Directive
  493.  
  494. Syntax: symbol-name = expression
  495.         symbol-name = built-in-symbol
  496.         symbol-name = INT n
  497.  
  498. The equals-sign directive is provided for compatiblity with That 
  499. Other assembler.  It is identical to the EQU directive, with one 
  500. exception: if the first time a symbol appears in a program is in 
  501. an = directive, that symbol will be taken as a local symbol.  It 
  502. can be redefined to other values, just like the generic local 
  503. symbols (letter followed by digits) that A86 supports.  This 
  504. facility is most often used to define "assembler variables", that 
  505. change value as the assembly progresses.
  506.                                                           9-11
  507. The PROC Directive
  508.  
  509. Syntax:  name  PROC NEAR
  510.          name  PROC FAR
  511.          name  PROC
  512.  
  513. PROC is a directive provided for compatibility with Intel/IBM 
  514. assemblers.  I don't like PROC; and I recommend that you do not 
  515. use it, even if you are programming for those assemblers.  
  516.  
  517. The idea behind PROC is to give the assembler a mechanism whereby 
  518. it can decide for you what kind of RET instruction you should be 
  519. providing.  If you specify NEAR in your PROC directive, then the 
  520. assembler will generate a near (same segment) return when it sees 
  521. RET.  If you specify FAR in your PROC directive, the assembler 
  522. will generate a far RETF return (which will cause both IP and CS 
  523. to be popped from the stack).  If you simply leave well enough 
  524. alone, and never code a PROC in your program, then RET will mean 
  525. near-return throughout your program.  
  526.  
  527. The reason I don't like PROC is because it is yet another attempt 
  528. by the assembler to do things "behind your back".  This goes 
  529. against the reason why you are programming in assembly language 
  530. in the first place, which is to have complete control over the 
  531. code generated by your source program.  It leads to nothing but 
  532. trouble and confusion.  
  533.  
  534. Another problem with PROC is its verbosity.  It replaces a simple 
  535. colon, given right after the label it defines.  This creates a 
  536. visual clutter in the program, that makes the program harder to 
  537. read.  
  538.  
  539. Even if you are programming in that other assembler, and you need 
  540. to code a far-return, I recommend that you create a RETF macro 
  541. (it would have the single line DB 0CBH), and stay away from PROCs 
  542. entirely.  
  543.                                                           9-12
  544.  
  545. The ENDP Directive
  546.  
  547. Syntax:   [name] ENDP
  548.  
  549. The only action A86 takes when it sees an ENDP directive is to 
  550. return the assembler to its (sane) default state, in which RET is 
  551. a near-return.  
  552.  
  553. NOTE that this means that A86 does not support nested PROCs, in 
  554. which anything but the innermost PROC has the FAR attribute.  I'm 
  555. sorry if I am blunt, but anybody who would subject their program 
  556. to that level of syntactic clutter has rocks in their head.  
  557.  
  558.  
  559. The LABEL Directive
  560.  
  561. Syntax:  name LABEL NEAR
  562.          name LABEL FAR
  563.          name LABEL BYTE
  564.          name LABEL WORD
  565.  
  566. LABEL is another directive provided for compatibility with 
  567. Intel/IBM assemblers.  A86 provides less verbose ways of 
  568. specifying all the above LABEL forms, except for LABEL FAR.  
  569.  
  570. LABEL defines "name" to have the type given, and a value equal to 
  571. the current output pointer.  Thus, LABEL NEAR is synonymous with 
  572. a simple colon following the name; and LABEL BYTE and LABEL WORD 
  573. are synonymous with DB and DW, respectively, with no operands.  
  574.  
  575. LABEL FAR does have a unique functionality, not found in other 
  576. assemblers.  It identifies "name" as a procedure that can be 
  577. called from outside this program's code segment.  Such procedures 
  578. should have RETFs instead of RETs. Furthermore, I have provided 
  579. the following feature, unique to A86: if you CALL the procedure 
  580. from within your program, A86 will generate a PUSH CS instruction 
  581. followed by a NEAR call to the procedure.  Other assemblers will 
  582. generate a FAR call, having the same functional effect; but the 
  583. FAR call consumes more program space, and takes more time to 
  584. execute.  
  585.  
  586. WARNING: you cannot use the above CALL feature as a forward-
  587. reference; the LABEL FAR definition must precede any CALLs to it.  
  588. This is unavoidable, since the assembler must assume that a CALL 
  589. to an undefined symbol takes 3 program bytes.  All assemblers 
  590. will issue an error in this situation.  
  591.  
  592.